<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\DistributionController;
use App\Http\Services\CommonManager;
use App\Http\Services\Wechat\WechatLogin;
use App\Http\Services\wxBizDataCrypt;
use App\Http\Services\YunPian;
use App\UserAuth;
use App\VerifyPhone;
use App\WxAuth;
use Illuminate\Http\Request;
use App\Exceptions\WechatException;
use Blocktrail\CryptoJSAES\CryptoJSAES;
use App\UserInfo;
use App\User;
use App\Files;
use Requests_Exception;
use Carbon\Carbon;
use App\Http\Services\FileManager;
use App\Http\Services\UserManager;
use App\Images;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use Cookie;

class AuthController extends Controller
{
    private $wechat_base_url = 'https://api.weixin.qq.com/sns/jscode2session';

    public function loginByOpenId(Request $request){
        $openId = $request->get('open_id');

        $token = CryptoJSAES::encrypt($openId,env('AES_KEY'));
        $cookie = Cookie::forever("user_token",$token);
        $url = 'https://tea.dindong.cn/';
        return redirect()->to($url)->cookie($cookie);
    }

    public function wxLogin(Request $request){
        $state = $request->get('state');

        $state = !is_null($state) ? $state : 0;
        $callbackUrl = route('Api.Auth.wechatCallback');
        $url         = WechatLogin::buildRedirectUrl($callbackUrl,$state);
        return redirect($url);
    }

    public function wechatCallback(Request $request){
        $code       = $request->get('code');
        $state      = $request->get('state');

        /** @var  WechatLogin $result */
        $result = WechatLogin::getWechatUserInfo($code);

        $accessToken = $result->getAccessToken();
        $openId      = $result->getOpenId();
        $nickname    = $result->getNickname();
        $sex         = $result->getSex();
        $headImgUrl  = $result->getHeadimgurl();
        $province    = $result->getProvince();
        $city        = $result->getCity();
        $unionid     = $result->getUnionid();


        /** @var UserAuth $newUserAuth */
        $newUserAuth = UserAuth::whereWxOpenid($openId)->first();
        if(!$newUserAuth) {
            $newUserAuth = new UserAuth();
            $newUserAuth->wx_openid      = $openId;
            $newUserAuth->wx_session_key = $accessToken;
            $newUserAuth->nickname       = $nickname;
            $newUserAuth->sex            = $sex;
            $newUserAuth->province       = $province;
            $newUserAuth->city           = $city;
            $newUserAuth->type           = "wx";
            $newUserAuth->save();

            /** @var Files $fileModel */
            $fileModel = FileManager::saveFileByWechatImg($headImgUrl,"oss");
            if ($fileModel) {
                $imageModel = Images::whereFileId($fileModel->id)->first();
                if (!$imageModel) {
                    $imageModel = new Images();
                    $imageModel->file_id = $fileModel->id;
                    $imageModel->img_name = 'wechat_img';
                    $imageModel->img_type = $fileModel->file_type;
                    $imageModel->save();

                    $newUserAuth->photo_id = $imageModel->id;
                    $newUserAuth->save();
                }else{
                    $newUserAuth->photo_id = $imageModel->id;
                    $newUserAuth->save();
                }
            }

            //记录用户信息
            /** @var User $newUser */
            $newUser = User::whereWxOpenid($openId)->first();
            if(!$newUser) {
                $newUser = new User();
                $newUser->wx_openid = $openId;
                $newUser->password = bcrypt('123456');
                $newUser->reg_ip = $request->ip();
                $newUser->reg_time = Carbon::now();
                $newUser->save();

                $newUser->user_key = md5($newUser->password . $newUser->id . time() . rand(0000, 9999));
                $newUser->save();

                $userInfo = new Userinfo();
                $userInfo->user_id = $newUser->id;
                $userInfo->nickname = $nickname;
                $userInfo->sex = $sex;
                $userInfo->province = $province;
                $userInfo->city = $city;
                $userInfo->photo_id = $newUserAuth->photo_id;
                $userInfo->picture = $headImgUrl;
                $userInfo->save();
            }

            $newUserAuth->user_id = $newUser->id;
            $newUserAuth->save();

            $token = CryptoJSAES::encrypt($newUserAuth->wx_openid,env('AES_KEY'));
            $cookie = Cookie::forever("user_token",$token);
            $url = 'https://tea.dindong.cn/';
            return redirect()->to($url)->cookie($cookie);
        }else{
            if($newUserAuth->user_id == 0){

                //记录用户信息
                /** @var User $newUser */
                $newUser = User::whereWxOpenid($openId)->first();
                if(!$newUser) {
                    $newUser = new User();
                    $newUser->wx_openid = $openId;
                    $newUser->password = bcrypt('123456');
                    $newUser->reg_ip = $request->ip();
                    $newUser->reg_time = Carbon::now();
                    $newUser->save();

                    $newUser->user_key = md5($newUser->password . $newUser->id . time() . rand(0000, 9999));
                    $newUser->save();

                    $userInfo = new Userinfo();
                    $userInfo->user_id = $newUser->id;
                    $userInfo->nickname = $newUserAuth->nickname;
                    $userInfo->sex = $newUserAuth->sex;
                    $userInfo->province = $newUserAuth->province;
                    $userInfo->city = $newUserAuth->city;
                    $userInfo->photo_id = $newUserAuth->photo_id;
//                    $userInfo->picture = $headImgUrl;
                    $userInfo->save();
                }

                $newUserAuth->user_id = $newUser->id;
                $newUserAuth->save();

                $token = CryptoJSAES::encrypt($newUserAuth->wx_openid,env('AES_KEY'));
                $cookie = Cookie::forever("user_token",$token);
                $url = 'https://tea.dindong.cn/';
                return redirect()->to($url)->cookie($cookie);
            }else{
                $thatUser = User::whereId($newUserAuth->user_id)->first();
                if(!$thatUser){
                    return response()->json(['level'=>'error','message'=>'系统错误']);
                }

                $token = CryptoJSAES::encrypt($thatUser->wx_openid,env('AES_KEY'));
                $cookie = Cookie::forever("user_token",$token);
                $url = 'https://tea.dindong.cn/';
                return redirect()->to($url)->cookie($cookie);
            }
        }
    }

    public function goToUrl(Request $request){
        $url = $request->get("url");
        return redirect()->to($url);
    }

    //小程序登录
    public function wxAppLogin(Request $request){
        $AppId          = env("WXAPP_KEY");
        $AppSecret      = env("WXAPP_SECRET");
        $code           = $request->get("code");
        $signature      = $request->get("signature");
        $rawData        = $request->get("raw_data");
        $invite_user_id = $request->get("invite_id");

        $wechatLogin = new AuthController();
        $wx_request_url = $wechatLogin->wechat_base_url."?appid=".$AppId."&secret=".$AppSecret."&js_code=".$code."&grant_type=authorization_code";

        try{
            $result = \Requests::get($wx_request_url,array(),array());
        }catch (Requests_Exception $ex){
            throw new WechatException(WechatException::WeChatSignInFail,['message' => $ex->getMessage()]);
        }

        if (!$result->success) {
            return false;
        }

        $res = json_decode($result->body);

        if(isset($res->errcode) && $res->errcode != 0){
            return response()->json(['level'=>'error','message'=>"授权错误","data"=>null]);
        }

        $openid      = $res->openid;
        $session_key = $res->session_key;

        // 数据签名校验
        $signature2 = sha1($rawData.$session_key);
        if ($signature != $signature2) {
            return response()->json(['level'=>'error','message'=>'获取失败']);
        }

        $wxInfo = json_decode($rawData,true);

        /** @var User $newUser */
        $newUser = User::whereWxOpenid($openid)->first();
        if(!$newUser) {
            $newUser = new User();
            $newUser->wx_openid = $openid;

            $newUser->wx_session_key = $session_key;
            $newUser->password = bcrypt('123456');
            $newUser->reg_ip = $request->ip();
            $newUser->reg_time = Carbon::now();
            $newUser->save();

            $newUser->user_key = md5($newUser->password.$newUser->id.time().rand(0000,9999));
            $newUser->save();

            $headImgUrl = $wxInfo["avatarUrl"];

            $userInfo = new Userinfo();
            $userInfo->user_id = $newUser->id;
            $userInfo->nickname = $wxInfo["nickName"];
            $userInfo->sex = $wxInfo["gender"];
            $userInfo->province = $wxInfo["province"];
            $userInfo->city = $wxInfo["province"];
            $userInfo->save();

            /** @var Files $fileModel */
            $fileModel = FileManager::saveFileByWechatImg($headImgUrl,"oss");
            if ($fileModel) {
                $imageModel = Images::whereFileId($fileModel->id)->first();
                if (!$imageModel) {
                    $imageModel = new Images();
                    $imageModel->file_id = $fileModel->id;
                    $imageModel->img_name = 'wechat_img';
                    $imageModel->img_type = $fileModel->file_type;
                    $imageModel->save();

                    $userInfo->photo_id = $imageModel->id;
                    $userInfo->save();
                }else{
                    $userInfo->photo_id = $imageModel->id;
                    $userInfo->save();
                }
            }

            $actionType = 'bind';
            //TODO 记录分享链
            if ($invite_user_id)
                DistributionController::joinMyTeam($invite_user_id,$newUser->id);
        }else{
            $newUser->wx_session_key = $session_key;
            $newUser->save();

            if(is_null($newUser->user_key) || $newUser->user_key == ''){
                $newUser->user_key = md5($newUser->password.$newUser->id.time().rand(0000,9999));
            }

            $thisUserInfo = UserInfo::whereUserId($newUser->id)->first();
            if(!$thisUserInfo){
                $thisUserInfo = new Userinfo();
                $thisUserInfo->user_id = $newUser->id;
                $thisUserInfo->nickname = $wxInfo["nickName"];
                $thisUserInfo->sex = $wxInfo["gender"];
                $thisUserInfo->province = $wxInfo["province"];
                $thisUserInfo->city = $wxInfo["province"];
                $thisUserInfo->save();
            }

            $headImgUrl = $wxInfo["avatarUrl"];

            /** @var Files $fileModel */
            $fileModel = FileManager::saveFileByWechatImg($headImgUrl,"oss");
            if ($fileModel) {
                $imageModel = Images::whereFileId($fileModel->id)->first();
                if (!$imageModel) {
                    $imageModel = new Images();
                    $imageModel->file_id = $fileModel->id;
                    $imageModel->img_name = 'wechat_img';
                    $imageModel->img_type = $fileModel->file_type;
                    $imageModel->save();

                    $thisUserInfo->photo_id = $imageModel->id;
                    $thisUserInfo->save();
                }else{
                    $thisUserInfo->photo_id = $imageModel->id;
                    $thisUserInfo->save();
                }
            }

            if(!is_null($newUser->phone) && $newUser->phone != ''){
                $actionType = 'home';
            }else{
                $actionType = 'bind';
            }
        }

        $token = CryptoJSAES::encrypt($openid,env('AES_KEY'));
        return response()->json(['level'=>"success","message"=>"获取成功","data"=>$token,'action' => $actionType]);
    }

    /**
     * 发送验证码
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function sendVerificationCode(Request $request)
    {
        $phone = $request->get('phone');
        $isAttact = VerifyPhone::whereIp($request->ip())->orderBy('created_at', 'desc')->first();
        $isAttact_count = VerifyPhone::whereIp($request->ip())->count();

        if(!preg_match("/^(1[34578])[0-9]{9}$/", $phone))
            return response()->json(['level' => 'error','message' => '请正确输入手机号码！']);

        if ($isAttact_count > 3 && $isAttact->created_at->timestamp + 60 > time())
            return response()->json(['level' => 'error', 'message' => '请等待60秒后再发送']);
        if ($isAttact_count > 24 && $isAttact->created_at->timestamp + 60 * 60 * 24 > time())
            return response()->json(['level' => 'error', 'message' => '不允许访问！']);

        $result = VerifyPhone::wherePhone($phone)->orderBy('created_at', 'desc')->first();
        if ($result && 60 + $result->created_at->timestamp > time())
            return response()->json(['level' => 'error', 'message' => '请等待60秒后再发送']);

        VerifyPhone::wherePhone($phone)->delete();

        $VerifyCodeByPhone = new VerifyPhone();
        $VerifyCodeByPhone->phone = $phone;
        $VerifyCodeByPhone->verify_code = sprintf("%04d", rand(1000, 9999));
        $VerifyCodeByPhone->ip = $request->ip();
        $VerifyCodeByPhone->ensure_session = '';

        $send = new YunPian();
        $send->sendBasicSmsWithCode($phone, $VerifyCodeByPhone->verify_code);

        $VerifyCodeByPhone->save();

        return response()->json(['level' => 'success', 'message' => trans('验证码发送成功')]);
    }

    /**
     * 绑定手机号
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Exception
     */
    public function bindingPhone(Request $request){
        /** @var User $user */
        $user = UserManager::isLogin($request);
        if(!$user)
            return response()->json(['level' => 'error','message' => '请先登录！','data' => 'no_login']);

        $phone = $request->get('phone');
        $verifyPhone = $request->get('verify_phone');

        if(is_null($phone) || $phone == '')
            return response()->json(['level' => 'error','message' => '手机号不能为空']);

        $phoneVerification = CommonManager::phoneVerification($phone);
        if(!$phoneVerification)
            return response()->json(['level' => 'error','message' => '请正确输入手机号码！']);

        /** @var VerifyPhone $verifyCodeByPhone */
        $verifyCodeByPhone=VerifyPhone::wherePhone(trim($phone))->whereVerifyCode(trim($verifyPhone))->first();
        if(!$verifyCodeByPhone || strtotime($verifyCodeByPhone->created_at) + 60 * 15 < time()){
            return response()->json(['level'=>'error','message' => '验证码不匹配或已过期']);
        }

        $verifyCodeByPhone -> delete();

        /** @var UserAuth $userAuth */
        $userAuth = UserManager::isWxOpenid($request);
        if($userAuth){
            /** @var User $newUser */
            $newUser = User::wherePhone($phone)->first();
            if($newUser){
                $userAuth->user_id = $newUser->id;
                $userAuth->save();
            }else{
                $newUser = UserManager::signUp($phone,'123456');
                if($newUser){
                    $newUserInfo = new Userinfo();
                    $newUserInfo->user_id = $newUser->id;
                    $newUserInfo->nickname = $userAuth->nickname;
                    $newUserInfo->photo_id = $userAuth->photo_id;
                    $newUserInfo->sex      = $userAuth->sex;
                    $newUserInfo->integral = 50;
                    $newUserInfo->province = $userAuth->province;
                    $newUserInfo->city     = $userAuth->city;
                    $newUserInfo->save();
                }else{
                    return response()->json(['level' => 'error','message' => '注册时系统错误！']);
                }
            }
        }else{
            $thatUser = User::wherePhone($phone)->first();
            if(!$thatUser){
                $newUser = UserManager::signUp($phone,'123456');
                if($newUser){
                    $newUserInfo = new Userinfo();
                    $newUserInfo->user_id = $newUser->id;
                    $newUserInfo->save();
                }else{
                    return response()->json(['level' => 'error','message' => '注册时系统错误！']);
                }
            }else{
                return response()->json(['level' => 'error','message' => '手机号已被注册！']);
            }
        }

        $token = CryptoJSAES::encrypt($newUser->user_key,env('AES_KEY'));
        $cookie = Cookie::forever("user_token",$token);

        return response()->json(['level' => 'success','message' => '绑定成功','data' => $token])->cookie($cookie);
    }

    /**
     * 获取user_token
     * @param $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function getUserToken($id = 4){
        /** @var User $user */
        $user = User::whereId($id)->first();
        if(!$user)
            return response()->json(['level' => 'error','message' => '用户不存在']);

        $openid = $user->user_key;

        $token = CryptoJSAES::encrypt($openid,env('AES_KEY'));

        return response()->json(['level' => 'success','message' => '获取成功','data' => $token]);
    }

    /**
     * 充值session_key
     * @param Request $request
     * @return bool|\Illuminate\Http\JsonResponse
     * @throws WechatException
     */
    public function resetSessionKey(Request $request){
        $AppId          = env("WXAPP_KEY");
        $AppSecret      = env("WXAPP_SECRET");
        $code           = $request->get("code");

        $wechatLogin = new AuthController();
        $wx_request_url = $wechatLogin->wechat_base_url."?appid=".$AppId."&secret=".$AppSecret."&js_code=".$code."&grant_type=authorization_code";

        try{
            $result = \Requests::get($wx_request_url,array(),array());
        }catch (Requests_Exception $ex){
            throw new WechatException(WechatException::WeChatSignInFail,['message' => $ex->getMessage()]);
        }

        if (!$result->success) {
            return false;
        }

        $res = json_decode($result->body);

        if(isset($res->errcode) && $res->errcode != 0){
            return response()->json(['level'=>'error','message'=>"授权错误","data"=>null]);
        }

        $openid      = $res->openid;
        $session_key = $res->session_key;

        /** @var User $newUser */
        $newUser = User::whereWxOpenid($openid)->first();
        if(!$newUser)
            return response()->json(['level' => 'error','message' => '该用户不存在']);

        $newUser->wx_session_key  = $session_key;
        $newUser->save();

        return response()->json(['level' => 'success','message' => 'session_key重置成功']);
    }

    /**
     * 获取微信绑定的手机号
     * @param Request $request
     * @return bool|\Illuminate\Http\JsonResponse
     * @throws WechatException
     */
    public function getWeChatPhone(Request $request){
        $userToken      = $request->get('user_token');
        $encryptedData  = $request->get('encryptedData');
        $iv             = $request->get('iv');
        $AppId          = env("WXAPP_KEY");
        $AppSecret      = env("WXAPP_SECRET");
        $code           = $request->get("code");

        /** @var User $user */
        $user = UserManager::isLogin($request);
        if(!$user)
            return response()->json(['level' => 'error','message' => '请先登录！','data' => 'no_login']);

        if(!is_null($code) && $code != ''){
            $wechatLogin = new AuthController();
            $wx_request_url = $wechatLogin->wechat_base_url."?appid=".$AppId."&secret=".$AppSecret."&js_code=".$code."&grant_type=authorization_code";

            try{
                $result = \Requests::get($wx_request_url,array(),array());
            }catch (Requests_Exception $ex){
                throw new WechatException(WechatException::WeChatSignInFail,['message' => $ex->getMessage()]);
            }

            if (!$result->success) {
                return false;
            }

            $res = json_decode($result->body);

            if(isset($res->errcode) && $res->errcode != 0){
                return response()->json(['level'=>'error','message'=>"授权错误","data"=>null]);
            }

            $openid      = $res->openid;
            $session_key = $res->session_key;

            /** @var User $newUser */
            $newUser = User::whereWxOpenid($openid)->first();
            if(!$newUser)
                return response()->json(['level' => 'error','message' => '该用户不存在']);

            $newUser->wx_session_key  = $session_key;
            $newUser->save();
        }else{
            $openid         = $user->wx_openid;
            $session_key    = $user->wx_session_key;
        }


        $pc = new wxBizDataCrypt($AppId, $session_key);

        $errCode = $pc->decryptData($encryptedData, $iv,$data);

        if($errCode == 0){
            return response()->json(['level' => 'success','message' => '获取成功','data' => $data,'openid' => $openid,'session_key' => $session_key,'encryptedData' => $encryptedData , 'iv' => $iv,'user_token' => $userToken]);
        }else{
            return response()->json(['level' => 'error','message' => '获取失败','data' => $errCode,'openid' => $openid,'session_key' => $session_key,'encryptedData' => $encryptedData , 'iv' => $iv,'user_token' => $userToken]);
        }
    }

    /**
     * 绑定微信获取的手机号
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function directBindingPhone(Request $request){
        /** @var User $user */
        $user = UserManager::isLogin($request);
        if(!$user)
            return response()->json(['level' => 'error','message' => '请先登录！','data' => 'no_login']);

        $phone = $request->get('phone');

        if(is_null($phone) || $phone == '')
            return response()->json(['level' => 'error','message' => '手机号不能为空']);

        $phoneVerification = CommonManager::phoneVerification($phone);
        if(!$phoneVerification)
            return response()->json(['level' => 'error','message' => '请正确输入手机号码！']);

        $isPhone = User::wherePhone($phone)->first();
        if($isPhone)
            return response()->json(['level' => 'error','message' => '该手机号已被注册']);

        $user->phone = $phone;
        $user->save();

        return response()->json(['level' => 'success','message' => '绑定成功']);
    }
}
